﻿using System;
using CID.Domain.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using CID.Domain.Operations;

namespace CID.Web.Models.Infrastructure
{
    public class ParameterValueViewModel : BaseViewModel<IParameterValue>
    {
        #region Properties
        public int ParameterId { get; set; }
        public string Parameter { get; set; }

        [JsonConverter(typeof(StringEnumConverter))]
        public ParameterType ParameterType { get; set; }

        public int? EnvironmentId { get; set; }
        public string Environment { get; set; }

        public string StringValue { get; set; }
        public int? IntegerValue { get; set; }
        public decimal? DecimalValue { get; set; }
        public DateTime? DateTimeValue { get; set; }
        public Guid? UniqueIdentifierValue { get; set; }
        public bool? BooleanValue { get; set; }
        public string XmlValue { get; set; }
        #endregion

        public ParameterValueViewModel() : base() { }

        public ParameterValueViewModel(IParameterValue model) : base(model) {
            SetParameterProperties(model.Parameter);

            switch (ParameterType)
            {
                case ParameterType.String: StringValue = model.StringValue; break;
                case ParameterType.Integer: IntegerValue = model.IntegerValue; break;
                case ParameterType.Decimal: DecimalValue = model.DecimalValue; break;
                case ParameterType.Boolean: BooleanValue = model.BooleanValue; break;
                case ParameterType.DateTime: DateTimeValue = model.DateTimeValue; break;
                case ParameterType.UniqueIdentifier: UniqueIdentifierValue = model.UniqueIdentifierValue; break;
                case ParameterType.Xml: XmlValue = ParameterValueSerializer.Serialize(model.XmlValue); break;
            }
        }

        public ParameterValueViewModel(IEnvironmentParameterValue model) : this(model as IParameterValue)
        {
            SetEnvironmentProperties(model.Environment);
        }

        public ParameterValueViewModel(IDefaultParameterValue model) : this(model as IParameterValue)
        {
            Environment = "*Default*";
        }

        public ParameterValueViewModel(IParameter parameter, IEnvironment enviroment) : base()
        {
            SetParameterProperties(parameter);
            SetEnvironmentProperties(enviroment);
        }

        private void SetParameterProperties(IParameter parameter)
        {
            ParameterId = parameter.Id;
            Parameter = parameter.Name;
            ParameterType = parameter.Type;
        }

        private void SetEnvironmentProperties(IEnvironment environment)
        {
            EnvironmentId = environment.Id;
            Environment = environment.Name;
        }

        [JsonIgnore]
        public bool HasValue
        {
            get
            {
                bool result = false;

                switch (ParameterType)
                {
                    case ParameterType.String: result = !String.IsNullOrEmpty(StringValue); break;
                    case ParameterType.Integer: result = IntegerValue.HasValue; break;
                    case ParameterType.Decimal: result = DecimalValue.HasValue; break;
                    case ParameterType.Boolean: result = BooleanValue.HasValue; break;
                    case ParameterType.DateTime: result = DateTimeValue.HasValue; break;
                    case ParameterType.UniqueIdentifier: result = UniqueIdentifierValue.HasValue; break;
                    case ParameterType.Xml: result = !String.IsNullOrEmpty(XmlValue); break;
                }
                return result;
            }
        }

        public override void UpdateModel(IParameterValue model)
        {
            if (ParameterId != model.Parameter.Id) throw new Exception("The IDs don't match");

            switch (ParameterType)
            {
                case ParameterType.String: model.StringValue = StringValue; break;
                case ParameterType.Integer: model.IntegerValue = IntegerValue.Value; break;
                case ParameterType.Decimal: model.DecimalValue = DecimalValue.Value; break;
                case ParameterType.Boolean: model.BooleanValue = BooleanValue.Value; break;
                case ParameterType.DateTime: model.DateTimeValue = DateTimeValue.Value; break;
                case ParameterType.UniqueIdentifier: model.UniqueIdentifierValue = UniqueIdentifierValue.Value; break;
                case ParameterType.Xml: model.XmlValue = ParameterValueSerializer.DeserializeAsXml(XmlValue); break;
            }
        }

        [JsonIgnore]
        public string DisplayValue
        {
            get
            {
                string result = String.Empty;
                switch (ParameterType)
                {
                    case ParameterType.String: result = ParameterValueSerializer.Serialize(StringValue); break;
                    case ParameterType.Integer: result = ParameterValueSerializer.Serialize(IntegerValue.Value); break;
                    case ParameterType.Decimal: result = ParameterValueSerializer.Serialize(DecimalValue.Value); break;
                    case ParameterType.Boolean: result = ParameterValueSerializer.Serialize(BooleanValue.Value); break;
                    case ParameterType.DateTime: result = ParameterValueSerializer.Serialize(DateTimeValue.Value); break;
                    case ParameterType.UniqueIdentifier: result = ParameterValueSerializer.Serialize(UniqueIdentifierValue.Value); break;
                    case ParameterType.Xml: result = XmlValue; break;
                }

                return result;
            }
        }
    }
}